#include "DownloadManagerTable.h"
#include "HttpDownloader.h"
#include "Settings.h"
#include <QDebug>
#include <QHeaderView>
#include <QtGui>
#include <QErrorMessage>

DownloadManagerTable::DownloadManagerTable(QWidget *parent) :
	QTableView(parent), runningDownloadsNumber(0)
{
	setItemDelegate(new DownloaderViewDelegate(this));
	setAlternatingRowColors(true);

	proxyModel = new MyQSortFilterProxyModel(this);
	sourceModel = new DataModel(proxyModel);
	proxyModel->setSourceModel(sourceModel);
	proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
	setModel(proxyModel);

	verticalHeader()->setResizeMode(QHeaderView::Fixed);
	horizontalHeader()->setResizeMode(3, QHeaderView::Fixed);

	connect(this, SIGNAL(newDownload(Download*)),
			sourceModel, SLOT(addDownload(Download*)));
	connect((qobject_cast<MainWindow*>(parent)), SIGNAL(save()),
			sourceModel, SLOT(save()));

	setSelectionMode(QAbstractItemView::SingleSelection);
	setSelectionBehavior(QAbstractItemView::SelectRows);
	setSortingEnabled(true);

	tryToStartPendingDownloads();
}

void DownloadManagerTable::removeSelectedDownload()
{
	if (!selectedIndexes().isEmpty()) {
		int progress = proxyModel->data(selectedIndexes()[DataModel::ProgressColumn]).toInt();
		if (progress < 100 &&
			Settings::getAskBeforeRemoveDownload() &&
			QMessageBox::question(this, tr("Deleting not finished download"),
								  tr("This download is not finished. "
									 "Are you sure you want to delete it?"),
								  QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
			== QMessageBox::No) {
			return;
		}

		int downloadId = proxyModel->data(selectedIndexes()[DataModel::IdColumn]).toInt();
		sourceModel->removeDownload(downloadId);
		clearSelection();
		emit isDownloadSelected(false);
		emit isRunningDownloadSelected(false);
		emit isNewDownloadSelected(false);
	}
}

void DownloadManagerTable::stopSelectedDownload()
{
	qDebug() << "DownloadManagerTable::stopSelectedDownload()";
	if (!selectedIndexes().isEmpty()) {
		if (Settings::getAskBeforeStopDownload() &&
			QMessageBox::question(this, tr("Stop download"),
								  tr("Download progress will be lost. "
									 "Are you sure you want to stop this download?"),
								  QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
			== QMessageBox::No) {
			return;
		}

		int downloadId = proxyModel->data(selectedIndexes()[DataModel::IdColumn]).toInt();
		sourceModel->stopDownload(downloadId);
		runningDownloadsNumber--;
		emit isRunningDownloadSelected(false);
		emit isNewDownloadSelected(true);
	}
}

void DownloadManagerTable::startSelectedDownload()
{
	if (!selectedIndexes().isEmpty()) {
		int downloadId = proxyModel->data(selectedIndexes()[DataModel::IdColumn]).toInt();
		startDownload(sourceModel->getDownload(downloadId));
		emit isRunningDownloadSelected(true);
		emit isNewDownloadSelected(false);
	}
}

void DownloadManagerTable::downloadFinished()
{
	runningDownloadsNumber--;
	tryToStartPendingDownloads();
}

void DownloadManagerTable::tryToStartPendingDownloads()
{
	for (int i = runningDownloadsNumber; i < Settings::getMaxParallelDownloadsNumber(); i++) {
		Download *nextDownload = sourceModel->getDownloadToStart();
		if (nextDownload != 0) {
			startDownload(nextDownload);
		} else {
			break;
		}
	}
}

void DownloadManagerTable::selectionChanged(const QItemSelection &selected,
											const QItemSelection &deselected)
{
	QTableView::selectionChanged(selected, deselected);

	if (!selected.isEmpty()) {
		emit isDownloadSelected(true);

		int downloadId = proxyModel->data(selectedIndexes()[DataModel::IdColumn]).toInt();
		bool isRunning = sourceModel->getDownload(downloadId)->isRunning();
		emit isRunningDownloadSelected(isRunning);

		bool isStarted = sourceModel->getDownload(downloadId)->isStarted();
		emit isNewDownloadSelected(
					!isStarted && runningDownloadsNumber < Settings::getMaxParallelDownloadsNumber());
	} else {
		emit isDownloadSelected(false);
		emit isRunningDownloadSelected(false);
		emit isNewDownloadSelected(false);
	}
}

QVariant DownloadManagerTable::getData(const QModelIndex &index)
{
	return proxyModel->data(index);
}

void DownloadManagerTable::startDownload(Download *download)
{
	HttpDownloader *downloader = new HttpDownloader(download->getDownloadLink(),
													download->getSavingPath(), this);

	if (downloader->downloadFile()) {
		download->setStarted(true);
		connect(downloader, SIGNAL(progressUpdated(int)), download, SLOT(setProgerss(int)));
		connect(downloader, SIGNAL(progressUpdated(int)), sourceModel, SLOT(update()));
		connect(downloader, SIGNAL(downloadFinished()), download, SLOT(finish()));
		connect(downloader, SIGNAL(downloadFinished()), this, SLOT(downloadFinished()));
		connect(download, SIGNAL(canceled()), downloader, SLOT(cancelDownload()));
		runningDownloadsNumber++;
	}
}



void DownloadManagerTable::createDownload(QString downloadLink, QString folder, int priority)
{
	QFileInfo fileInfo(downloadLink);
	QString fileName = fileInfo.fileName();

	QDir directory(folder);
	folder = directory.absolutePath();
	QString filePath = directory.filePath(fileName);

	if (QFile::exists(filePath)) {
		if (sourceModel->isDuplicateDownload(folder, fileName)) {
			QMessageBox::about(this, tr("Duplicate download"),
					tr("File %1 is already being downloaded to specified directory.").arg(fileName));
			return;
		} else if (Settings::getAskBeforeOverwrite() &&
				   QMessageBox::question(this, tr("File exists"),
										 tr("There already exists a file with name %1 in "
											"the specified directory. Overwrite?").arg(fileName),
										 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
				   == QMessageBox::No) {
			return;
		} else {
			QFile::remove(filePath);
		}
	}

	Download *download = new Download(fileName, folder, downloadLink, priority);
	emit newDownload(download);

	if (runningDownloadsNumber < Settings::getMaxParallelDownloadsNumber()) {
		startDownload(download);
	}
}
